<script setup lang="ts">
import { ref } from 'vue'
import { Select, Button } from 'ant-design-vue'
import { components } from './components.ts'
import { randomId } from './utils.ts'
import { createNavigation } from './navigation.ts'

const options = Object.keys(components).map((key) => ({
    label: components[key].name,
    value: key
}))

const selectComponent = ref<string>()
const [schema, navigator, queue, current] = createNavigation<{
    id: string
    component: string
    props: any
}[]>([])

const addComponent = () => {
    if (!selectComponent.value) return
    const component = components[selectComponent.value]
    const id = randomId()
    const data = component.configure.data({
        onChange: (value: any) => {
            const index = schema.value.findIndex((item) => item.id === id)
            if (value === -1 || value === data.value) return
            navigator.replace(`${index}.props.value`, value, `更新${component.name}组件值：${value}`)
        }
    })
    navigator.add(String(schema.value.length), {
        id,
        component: selectComponent.value,
        props: data
    }, `新增组件${selectComponent.value}`)
}

const removeComponent = (id: string) => {
    const index = schema.value.findIndex((item) => item.id === id)
    navigator.remove(String(index), `删除组件${schema.value.find((item) => item.id === id)?.component}`)
}

const moveComponent = (id: string, direction: 'up' | 'down') => {
    const index = schema.value.findIndex((item) => item.id === id)
    if (direction === 'up' && index > 0) {
        navigator.move(String(index), String(index - 1), `上移组件${schema.value[index].component}`)
    }
    if (direction === 'down' && index < schema.value.length - 1) {
        navigator.move(String(index), String(index + 1), `下移组件${schema.value[index].component}`)
    }
}
</script>

<template>
    <div class="container">
        <main>
            <div class="action">
                <Select
                    v-model:value="selectComponent"
                    :style="{
                    minWidth: '200px'
                }"
                    :options="options"
                />
                <Button @click="addComponent">新增一行</Button>
            </div>
            <div class="editor">
                <template v-for="item in schema" :key="item.id">
                    <div class="editor-item">
                        <component :is="components[item.component].component" v-bind="item.props" />
                        <Button @click="removeComponent(item.id)">删除</Button>
                        <Button @click="moveComponent(item.id, 'up')">上移</Button>
                        <Button @click="moveComponent(item.id, 'down')">下移</Button>
                    </div>
                </template>
            </div>
        </main>
        <aside>
            <div class="action">
                <Button @click="navigator.undo()" :disabled="current === undefined">撤销</Button>
                <Button @click="navigator.redo()" :disabled="current === queue.length - 1">重做</Button>
            </div>
            <template v-for="(task, index) in queue" :key="task.id">
                <div
                    class="task"
                    :style="{
                        fontWeight: index === current ? 'bold' : 'normal'
                    }"
                >
                    <div>{{ task.description }}</div>
                    <Button @click="navigator.jump(index)">跳转</Button>
                </div>
            </template>
        </aside>
    </div>
</template>

<style scoped>
.container {
    display: flex;
    justify-content: space-between;
    padding: 20px;

    main {
        margin-top: 100px;
        padding: 0 100px;
        width: 55%;

        .action {
            padding: 20px;
            display: flex;
            justify-content: center;
            background-color: #f0f2f5;

            > * {
                margin-right: 20px;
            }
        }

        .editor {
            padding: 20px;
            background-color: #f0f2f5;

            .editor-item {
                margin-bottom: 20px;
                padding: 20px;
                background-color: #fff;
                display: flex;
                justify-content: space-between;

                > * {
                    margin-right: 20px;
                }
            }
        }
    }

    aside {
        margin-top: 100px;
        width: 40%;

        .action {
            padding: 10px;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;

            > * {
                margin-right: 20px;
            }
        }

        .task {
            padding: 5px;
            background-color: #fff;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }

}
</style>
